﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using MagicKey.Components.UserManager;
using MagicKey.Factory;
using MagicKey.Interfaces;
using Microsoft.Win32;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;

namespace MagicKey.UserInterface
{
    /// <summary>
    /// Interaktionslogik für Fileviewer.xaml
    /// </summary>
    public partial class Fileviewer : Window
    {
        #region Fields

        readonly IAccessManager _accessManager = MagicKeyFactory.GetInstance().GetMagicKeyInterface().GetAccessManager();
        readonly IUserManager _userManager = MagicKeyFactory.GetInstance().GetMagicKeyInterface().GetUserManager();
        readonly IFileAccess _fileAccess = MagicKeyFactory.GetInstance().GetMagicKeyInterface().GetFileAccess();

        private ManageAuthorizations _manageAuthorizations;
        private User _masterUser;
        private List<string> _filesList;
        private List<User> _allUsers;

        #endregion

        #region Constructors

        public Fileviewer(MainWindow myWindow)
        {
            IsSelectedFileDecrypt = false;
            InitializeComponent();

            // The following line enables the tremble effect for the current
            // window when clicking on the main window
            this.Owner = myWindow;

            this._masterUser = new User();
            _masterUser.Name = myWindow.MasterUser;
            this.CurrentUserLabel.Content += " " + _masterUser.Name + " !";

            RefreshfileList();
        }

        #endregion Constructors

        #region Properties

        public string SelectedFile { get; set; }

        public bool IsSelectedFileDecrypt { get; set; }

        public User MasterUser
        {
            get
            {
                return this._masterUser;
            }

            set
            {
                this._masterUser = value;
            }
        }


        public List<User> AllUsers
        {
            get
            {
                return this._allUsers;
            }

            set
            {
                this._allUsers = value;
            }
        }
        #endregion

        #region Methods

        public void RefreshfileList()
        {
            this._userManager.LoadAllUsers();

            _allUsers = ((UserManager)this._userManager).Users;

            this._filesList = new List<string>();

            foreach (User u in _allUsers)
            {
                if (u.Name.Equals(_masterUser.Name))
                {
                    this._masterUser = u;
                    foreach (string s in u.MyFiles)
                    {
                        this._filesList.Add(s);
                    }

                    foreach (string s in u.OtherUserFiles)
                    {
                        this._filesList.Add(s);
                    }

                    break;
                }
            }

            this.FileListBox.ItemsSource = this._filesList;
        }

        #endregion Methods

        #region Events

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FileListBox_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            SelectedFile = (string)this.FileListBox.SelectedItem;

            var pv = new PasswordViewer(this);

            //show a password dialog and open a selected file if password is correct
            pv.ShowDialog();

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadDocumentButton_Click(object sender, RoutedEventArgs e)
        {

            // Create OpenFileDialog
            var openFileDialog = new OpenFileDialog
            {
                // Set filter for file extension
                DefaultExt = ".txt",

                // default file extension
                Filter = "TXT Files (*.txt)|*.txt|CS Files (*.cs)|*.cs|SQL Files (*.sql)|*.sql|All files (*.*)|*.*" 
            };


            // Display OpenFileDialog by calling ShowDialog method
            var result = openFileDialog.ShowDialog();

            // Get the selected file name and display in a TextBox
            if (result != true) return;

            // user symetric key
            var userSymetricKey1 = _userManager.GetUserSymetricKey(_masterUser.Name);
            var key = _masterUser.Role;
            var userSymetricKey = _accessManager.DecryptStringSym(userSymetricKey1, key);
            key = null;

            //encrypt a file symetric
            var localFileSymEncrpted = _accessManager.EncryptFileSym(openFileDialog.FileName, userSymetricKey);

            //upload of the server
            var filename = _fileAccess.UploadFile(localFileSymEncrpted, _masterUser.Id);

            var idOfInsertedFile = _userManager.InsertUserFile(filename, _masterUser.Id);

            if (idOfInsertedFile == 0) return;

            // user public key
            var userPublicKey = _userManager.GetPublicKey(_masterUser.Name);

            //encrypt a file asymetric
            var encryptedSymetricKey = _accessManager.EncryptStringAsym(userPublicKey, userSymetricKey);
            userSymetricKey = null;

            //inserted  encrypted user sysmetric key in database
            bool isIAuthorisationInserted = _accessManager.InsertAuthorisationAccess(_masterUser.Id, _masterUser.Id, idOfInsertedFile, encryptedSymetricKey, encryptedSymetricKey);

            //check if data was inserted
            if (!isIAuthorisationInserted) return;
            
            // Important wait Garbace Collector
            GC.Collect();
            GC.WaitForPendingFinalizers();

            //Check if File Exist
            if (File.Exists(localFileSymEncrpted))
                File.Delete(localFileSymEncrpted);

            //---------------------------------- Insert the file in the d.atabase

            if (!filename.Equals(string.Empty))
            {
                // Refresh the file listbox
                RefreshfileList();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ManageAuthorizationsButton_Click(object sender, RoutedEventArgs e)
        {
            _manageAuthorizations = new ManageAuthorizations(this);
            _manageAuthorizations.ShowDialog();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FileListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            if (this.FileListBox.SelectedIndex != -1)
            {
                // A file has been selected!

                var selectedItem = (string)this.FileListBox.SelectedItem;

                string ownerName = _userManager.GetOwnerName(selectedItem);

                this.FileOwnerLabel.Content = "File owner: " + ownerName;

                if (ownerName.Equals(_masterUser.Name))
                {
                    this.DeleteFileButton.IsEnabled = true;
                    this.ManageAuthorizationsButton.IsEnabled = true;
                }
                else
                {
                    this.DeleteFileButton.IsEnabled = false;
                    this.ManageAuthorizationsButton.IsEnabled = false;
                }

            }
            else
            {
                this.DeleteFileButton.IsEnabled = false;
                this.ManageAuthorizationsButton.IsEnabled = false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DeleteFileButton_Click(object sender, RoutedEventArgs e)
        {
            //Check if current user is a Owner
            var selectedIndex = this.FileListBox.SelectedIndex;

            var selectedItem = (string)this.FileListBox.SelectedItem;

            if (this._masterUser.MyFiles.Contains(selectedItem))
            {
                if (_fileAccess.DeleteFile(selectedItem, this._masterUser.Id))
                {
                    this._filesList.RemoveAt(selectedIndex);
                    this.RefreshfileList();
                }
            }
            else
            {
                MessageBox.Show("You cannot access this file!", "Fileviewer",
                                      MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Fileviewer_OnClosing(object sender, CancelEventArgs e)
        {
            const string msg = "Do you really want to logout?";

            var result = MessageBox.Show(msg, "Fileviewer",
                                      MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (result == MessageBoxResult.No)
            {
                // If user doesn't want to close, cancel closure
                e.Cancel = true;
            }
            else
            {
                ((MainWindow)this.Owner).Init();
                e.Cancel = false;
            }
        }

      

        private void Logout_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        #endregion Events

    }
}
